package com.sfac.springboot.springboot.config.shiro;

import com.sfac.springboot.springboot.modules.account.entity.Resource;
import com.sfac.springboot.springboot.modules.account.entity.Role;
import com.sfac.springboot.springboot.modules.account.entity.User;
import com.sfac.springboot.springboot.modules.account.service.ResourceService;
import com.sfac.springboot.springboot.modules.account.service.RoleService;
import com.sfac.springboot.springboot.modules.account.service.UserService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * @Description MyRealm
 * @Author JiangHu
 * @Date 2022/8/31 9:40
 */
@Component
public class MyRealm extends AuthorizingRealm {

	@Autowired
	private UserService userService;
	@Autowired
	private RoleService roleService;
	@Autowired
	private ResourceService resourceService;

	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

		SimpleAuthorizationInfo authorization = new SimpleAuthorizationInfo();

		// 从认证中获取当前的信息
		User user = (User) principals.getPrimaryPrincipal();

		// 从数据库查询当前用户的角色列表，并装载到资源授权器里
		List<Role> roles = roleService.getRolesByUserId(user.getId());
		roles.stream().forEach(item -> {
			authorization.addRole(item.getRoleName());

			// 再去查询每个角色拥有的资源列表，并装载到资源授权器里
			List<Resource> resources = resourceService.getResourcesByRoleId(item.getId());
			resources.stream().forEach(it -> {
				authorization.addStringPermission(it.getPermission());
			});
		});

		return authorization;
	}

	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
			throws AuthenticationException {
		// 获取用户名
		String userName = (String) token.getPrincipal();

		// 通过用户名查找数据库的 user 信息
		User user = userService.getUserByUserName(userName);
		if (user == null) {
			throw new UnknownAccountException("User name is not exit.");
		}

		// 封装身份验证器
		return new SimpleAuthenticationInfo(user, user.getPassword(), getName());
	}
}
